package com.beta.platform.rest.controller;

import com.beta.platform.rest.auth.DataAuthType;
import com.beta.platform.rest.auth.LoginAccountDetail;
import com.beta.platform.rest.auth.LoginAccountSecurity;
import com.beta.platform.rest.constant.RequestHeaderNames;
import com.beta.platform.rest.constant.dic.LanguageEnum;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 所有Controller必须要继承 所有获取用户信息的操作必须在Controller完成，service层不能去获取当前用户的信息，
 * 如果service需要当前用户信息，请在controller端传入
 * <p>
 * 不适用当子类是DubboService的时候
 *
 * @author sys
 */
@Log4j2
public class BaseController {

    /**
     * 支持页面上传入字符串2000-01-01的格式能转为Date
     *
     * @param binder
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String value) {
                Date date = null;
                try {
                    long time = Long.parseLong(value);
                    date = new Date(time);
                    setValue(date);
                } catch (Exception e) {
                    log.error("Bind string to date error:", e.getMessage());
                }
                if (date == null) {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                    try {
                        setValue(dateFormat.parse(value));
                    } catch (ParseException e) {
                        log.error("Bind string to date error:", e.getMessage());
                    }
                }
            }
        });
    }

    /**
     * 如果是后台用户返回表user的id，如果是c端用户返回表account的id
     *
     * @return
     */
    protected String getLoginAccountId() {
        LoginAccountDetail account = LoginAccountSecurity.getLoginAccountDetail();
        return account == null ? null : account.getId();
    }

    /**
     * 如果是扫码登录则想要获取第三方用户身份，调用这个接口
     *
     * @return
     */
    protected String getLoginThirdUserId() {
        LoginAccountDetail account = LoginAccountSecurity.getLoginAccountDetail();
        if (account == null) {
            return null;
        }

        return account.getThirdUserInfo() == null ? null : account.getThirdUserInfo().getUserId();
    }

    protected Long getPartnerId() {
        LoginAccountDetail account = LoginAccountSecurity.getLoginAccountDetail();
        return account == null ? null : account.getPartnerId();
    }

    /**
     * 获取数据权限的数据id
     *
     * @param dataAuthType
     * @return
     */
    protected List<Long> getDataAuthList(DataAuthType dataAuthType) {
        try {
            return getDataItems(dataAuthType).stream().map(LoginAccountDetail.DataItem::getId).collect(Collectors.toList());
        } catch (Exception err) {
            return Collections.emptyList();
        }
    }

    /**
     * 获取数据权限的数据code
     *
     * @param dataAuthType
     * @return
     */
    protected List<String> getDataAuthCodeList(DataAuthType dataAuthType) {
        try {
            return getDataItems(dataAuthType).stream().map(LoginAccountDetail.DataItem::getCode).collect(Collectors.toList());
        } catch (Exception err) {
            return Collections.emptyList();
        }
    }

    /**
     * 获取数据权限的列表
     *
     * @param dataAuthType
     * @return
     */
    protected List<LoginAccountDetail.DataItem> getDataItems(DataAuthType dataAuthType) {
        final LoginAccountDetail accountDetail = getLoginAccountDetail();
        if (accountDetail == null) {
            return Collections.emptyList();
        }
        LoginAccountDetail.DataAuth dataAuth = getLoginAccountDetail().getDataAuths().stream()
                .filter(da -> da.getType().equals(dataAuthType)).findFirst().orElse(null);
        if (dataAuth == null) {
            return Collections.emptyList();
        }
        return dataAuth.getDataItemList();
    }

    protected LoginAccountDetail getLoginAccountDetail() {
        return LoginAccountSecurity.getLoginAccountDetail();
    }

    protected LoginAccountDetail getLoginUserDetail() {
        return LoginAccountSecurity.getLoginAccountDetail();
    }

    protected LanguageEnum getLanguage() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        }
        HttpServletRequest request = requestAttributes.getRequest();
        return getLanguage(request, () -> LanguageEnum.CHINESE_CHINA);
    }

    /**
     * 获取请求对像
     *
     * @return
     */
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        }
        return requestAttributes.getRequest();
    }

    /**
     * 获取输出对象
     *
     * @return
     */
    public static HttpServletResponse getResponse() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        }
        return requestAttributes.getResponse();
    }

    /**
     * 获取多国语言版本
     *
     * @param defaultLanguage
     * @return
     */
    public static LanguageEnum getLanguage(HttpServletRequest req, Supplier<LanguageEnum> defaultLanguage) {
        try {
            final String languageStr = req.getHeader(RequestHeaderNames.X_LANGUAGE.getValue());
            if (StringUtils.isEmpty(languageStr)) {
                return defaultLanguage.get();
            }

            for (LanguageEnum languageEnum : LanguageEnum.values()) {
                if (languageEnum.getCode().equalsIgnoreCase(languageStr)) {
                    return languageEnum;
                }

                if (languageEnum.getLanguageGroup().contains(languageStr)) {
                    return languageEnum;
                }
            }
        } catch (Exception err) {
            return defaultLanguage.get();
        }
        return defaultLanguage.get();
    }

}
